<?php

// $Id$

/**
 * Contains class Tree_Menu_DBC_File_Importer
 *
 * @package modules
 * @subpackage  tree_menu
 */

/**
 *
 */
require_once(TANGRA_MAIN_DIR.'db/db_connection.class.php');

/**
 *
 */
require_once('tree_menu_dbc.class.php');
/**
 *
 */
require_once('tree_menu_item_dbc.class.php');


/**
 *
 */
require_once('te_tree_menu_dbc_import_file_failed.class.php');


/**
 * Tree_Menu_DBC_File_Importer is used to import tree menu items from XML file
 *
 * Example for importing new items:
 *
 * <?xml version="1.0" encoding="utf-8"?>
 * <menuimportfile>
 * 	<menuimport>
 * 		<menuitem>
 * 			<hid>test_item</hid>
 * 			<parenthid>Core</parenthid>
 * 			<label>Test</label>
 * 			<link>test.php</link>
 * 			<target>_blank</target>
 * 			<order>100</order>
 * 		</menuitem>
 * 	</menuimport>
 * </menuimportfile>
 *
 *
 *
 * Example for deleting menu items:
 *
 * <?xml version="1.0" encoding="utf-8"?>
 * <menuimportfile>
 * 	<menuitemsdelete>
 * 		<itemhid>presni</itemhid>
 * 	</menuitemsdelete>
 * </menuimportfile>
 *
 */
class Tree_Menu_DBC_File_Importer extends Tangra_Class {
	private $db_tables_prefix;
	private $update_existing;



	public function get_db_tables_prefix() {
		return $this->db_tables_prefix;
	}


	public function set_update_existing($update_existing) {
		$this->update_existing = $update_existing ? true : false;
	}


	public function get_update_existing() {
		return $this->update_existing;
	}


	public function import(DB_Connection $dbc, Tree_Menu_DBC $menu, $import_dir, $update_existing = false, $db_tables_prefix) {
		$ret = array();

		$this->db_tables_prefix = $db_tables_prefix;
		$this->set_update_existing($update_existing);

		if (file_exists($import_dir)) {
			if (is_dir($import_dir)) {
				$imported_items = array();
				$files = $this->get_files_for_import($import_dir);
				foreach($files as $file) {
					$imported_items[] = $this->import_from_file($import_dir.$file);
				}

				foreach($imported_items as $items_arr) {
					if ($items_arr) {
						if (array_key_exists('new_items', $items_arr)) {
							$menu = $this->import_new_items($menu, $items_arr['new_items']);

							try {
								$dbc->start_trans();
								$menu->save($dbc);
								$dbc->complete_trans();
							} catch(Exception $e) {
								$dbc->fail_trans();
								$dbc->complete_trans();
								throw $e;
							}
						} elseif (array_key_exists('delete_items', $items_arr)) {
							try {
								$dbc->start_trans();
								foreach($items_arr['delete_items'] as $item_hid) {
									$this->delete_item($dbc, $menu, $item_hid, $this->get_db_tables_prefix());
								}
								$dbc->complete_trans();
							} catch(Exception $e) {
								$dbc->fail_trans();
								$dbc->complete_trans();
								throw $e;
							}
						}
					}
				}

				$ret['files'] = $files;
				$ret['menu'] = $menu;
			} else {
				throw new TE_Tree_Menu('$dir is not directory: '.$import_dir);
			}
		} else {
			throw new TE_Tree_Menu('Import directory does not exist: '.$import_dir);
		}

		return $ret;
	}


	private function get_files_for_import($import_dir) {
		$ret = array();

		if ($dir = opendir($import_dir)) {
			while (($item = readdir($dir)) !== false) {
				if ($item != '.' && $item != '..') {
					if (is_file("$import_dir/$item")) {
						if (fnmatch('*.xml', $item)) {
							$ret[] = $item;
						}
					}
				}
			}
			closedir($dir);
		}

		return $ret;
	}


	public function import_from_file($file) {
		$ret = false;

		$xml = @simplexml_load_file($file);

		if ($xml) {
			if ($xml->menuimport) {
				$imported_items = array();
				foreach($xml->menuimport->menuitem as $item) {
					if (!trim($item->label)) {
						throw new TE_Tree_Menu('Empty or missing label.');
					}
					$raw_arr[0] = trim($item->label);
					$raw_arr[1] = trim(strtolower($item->parenthid));
					$raw_arr[2] = trim($item->link);
					if (!trim($item->hid)) {
						throw new TE_Tree_Menu('Empty or missing hid.');
					}
					$raw_arr[3] = trim($item->hid);
					$raw_arr[4] = trim($item->target);
					$raw_arr[5] = trim($item->order);

					$imported_items[] = Tree_Menu_Item_DBC::create_from_import_data($raw_arr, $this->get_db_tables_prefix().'menu');
					$ret['new_items'] = $imported_items;
				}
			}
		} else {
			throw new TE_Tree_Menu_DBC_Import_File_Failed('File '.$file.' is not valid import XML file.');
		}


		return $ret;
	}


	private function import_new_items(Tree_Menu_DBC $menu, $items_arr) {
		foreach($items_arr as $item) {
			$parent_hid = $item['parent_hid'];
			$item = $item['item'];

			if ($parent_hid) {
				$parent = $menu->find_item($parent_hid);
				if ($parent) {
					if (!$parent->subitem_exists($item)) {
						$parent->add_subitem($item);
					} else {
						if ($this->update_existing) {
							$parent->update_subitem($item);
						}
					}
				} else {
					throw new TE_Tree_Menu('Cannot find parend with hid = '.$parent_hid);
				}
			} else {
				if (!$menu->item_exists($item)) {
					$item->set_parent(0);
					$menu->add_item($item);
				} else {
					if ($this->update_existing) {
						$item->set_parent(0);
						$menu->update_item($item);
					}
				}
			}
		}

		return $menu;
	}


	protected function delete_item(DB_Connection $dbc, Tree_Menu_DBC $menu, $item_hid) {
		$item = $menu->find_item($item_hid);
		if ($item) {
			$id = $item->get_id();
			if ($id) {
				Tree_Menu_Item_DBC::delete($dbc, $id, $this->get_table());
			}
		}
	}
}